﻿using System;
using System.Collections.Generic;

using Apache.Cassandra;
using Client = Apache.Cassandra.Cassandra.Client;

using RexToy.Cassandra.Meta;

namespace RexToy.Cassandra
{
    internal abstract class ColumnFamilyBase<K, C>
    {
        private string _columnFamily;
        private string _keyspace;
        protected Client _c;
        protected ColumnFamilyInfo _info;
        protected Apache.Cassandra.ConsistencyLevel _read, _write;
        protected ColumnFamilyBase(string keyspace, string columnFamily, ColumnFamilyInfo info, Client c, ConsistencyLevel read, ConsistencyLevel write)
        {
            columnFamily.ThrowIfNullOrEmptyArgument("cfName");
            keyspace.ThrowIfNullOrEmptyArgument("ksName");
            info.ThrowIfNullArgument("info");
            c.ThrowIfNullArgument("c");

            _keyspace = keyspace;
            _columnFamily = columnFamily;
            _info = info;
            _c = c;
            _read = (Apache.Cassandra.ConsistencyLevel)read;
            _write = (Apache.Cassandra.ConsistencyLevel)write;
        }

        public string Name
        {
            get { return _columnFamily; }
        }

        protected byte[] GetColumnBytes(object column)
        {
            return _info.Comparator.GetBytes(column);
        }

        protected C GetColumnData(byte[] column)
        {
            return (C)_info.Comparator.GetData(column);
        }

        protected byte[] GetKeyBytes(K key)
        {
            return _info.KeyValidation.GetBytes(key);
        }

        protected K GetKeyData(byte[] bytes)
        {
            return (K)_info.KeyValidation.GetData(bytes);
        }

        protected byte[] GetValueBytes(object column, object val)
        {
            var colInfo = _info.GetColumnInfo(column);
            byte[] bytes;
            if (colInfo == null)
            {
                bytes = _info.DefaultValidation.GetBytes(val);
            }
            else
            {
                bytes = colInfo.Validation.GetBytes(val);
            }
            return bytes;
        }

        protected object GetValueData(object column, byte[] bytes)
        {
            var colInfo = _info.GetColumnInfo(column);
            object val;
            if (colInfo == null)
            {
                val = _info.DefaultValidation.GetData(bytes);
            }
            else
            {
                val = colInfo.Validation.GetData(bytes);
            }
            return val;
        }

        protected long GetTimeStamp()
        {
            return DateTime.Now.Ticks;
        }

        protected List<byte[]> ConvertKeyList(IEnumerable<K> keys)
        {
            List<byte[]> byteKeys = new List<byte[]>();
            foreach (var key in keys)
            {
                byteKeys.Add(this.GetKeyBytes(key));
            }
            return byteKeys;
        }

        protected virtual IRow<K, C> CreateRow(K key, IColumnCollection<C> collection)
        {
            throw new NotImplementedException();//Note:Each class should provide it's own impl.
        }
    }
}
